package dateFitting;

import java.util.Arrays;

public class ParameterFitting {
    public static void main(String[] args) {
        // 已知的数据
        double[] averages = {1, 0.7, 0.5, 0.42, 0.34, 0.25}; // 平均单件比率
        int[] quantities = {1, 3, 5, 10, 20, 50}; // 件数

        // 找到 M 和 alpha
        double[] params = findParameters(averages, quantities);
        double M = params[0];
        double alpha = params[1];

        System.out.printf("Optimal M: %.6f%n", M);
        System.out.printf("Optimal Alpha: %.6f%n", alpha);

        // 计算总时间（假设单位时间 t = 1，并输出结果）
        for (int r : quantities) {
            double totalTime = calculateTotalTime(r, M, alpha);
            System.out.printf("Total time for %d items: %.6f%n", r, totalTime);
        }
    }

    public static double[] findParameters(double[] averages, int[] quantities) {
        double M = 0.5; // 初始猜测值
        double alpha = -1.0; // 初始猜测值
        double learningRate = 0.001; // 学习率
        int maxIterations = 10000; // 最大迭代次数

        // 基准值
        double pBar = 1; // 假设基准值为 1

        for (int iteration = 0; iteration < maxIterations; iteration++) {
            double dM = 0; // 对 M 的误差梯度
            double dAlpha = 0; // 对 alpha 的误差梯度

            double error = 0; // 总误差

            // 遍历所有数据点
            for (int i = 0; i < averages.length; i++) {
                int r = quantities[i];

                // 计算平均单件比率
                double predictedAverage = 0;
                for (int k = 1; k <= r; k++) {
                    predictedAverage += (M + (1 - M) * Math.pow(k, alpha)) * pBar;
                }
                predictedAverage /= r;

                double actualAverage = averages[i];
                double diff = predictedAverage - actualAverage;
                error += diff * diff; // 误差平方

                // 计算梯度
                for (int k = 1; k <= r; k++) {
                    double singleRatio = (M + (1 - M) * Math.pow(k, alpha)) * pBar;
                    dM += 2 * diff * (1 - Math.pow(k, alpha)) / r;
                    dAlpha += 2 * diff * (1 - M) * Math.pow(k, alpha) * Math.log(k) / r;
                }
            }

            // 更新参数
            M -= learningRate * dM;
            alpha -= learningRate * dAlpha;

            // 打印每次迭代的误差（可选用于观察优化过程）
            if (iteration % 1000 == 0) {
                System.out.printf("Iteration %d, Error: %.6f%n", iteration, error / averages.length);
            }
        }

        return new double[]{M, alpha};
    }

    public static double calculateTotalTime(int r, double M, double alpha) {
        double totalTime = 0;
        double pBar = 1; // 单位时间基准值

        for (int k = 1; k <= r; k++) {
            // 单件时间
            double singleTime = (M + (1 - M) * Math.pow(k, alpha)) * pBar;
            totalTime += singleTime; // 累计总时间
        }

        return totalTime;
    }
}
